import copy
import json
import math
import os

import pandas as pd


def sort_by_pre_base_station(data):
    # 构建映射：preBaseStationID -> current ID
    prev_map = {}
    all_ids = set(data.keys())
    for node_id, info in data.items():
        prev_id = info.get("preBaseStationID")
        if isinstance(prev_id, float) and math.isnan(prev_id):  # 处理 nan
            prev_id = None
        if prev_id is not None:
            prev_map[prev_id] = node_id
    # 找到起点（preBaseStationID 为 nan 或 None）
    start_id = None
    for node_id in all_ids:
        if node_id not in prev_map.values():
            start_id = node_id
            break
    if not start_id:
        raise ValueError("找不到起点，可能存在循环依赖")
    # 遍历链表构建顺序列表
    result = []
    current_id = start_id
    while current_id:
        result.append(current_id)
        current_id = prev_map.get(current_id)

    return result


def build_section_dict(route_list, point_details, section_id):
    section_dict = {}

    for i in range(len(route_list) - 1):
        up_id = route_list[i]
        down_id = route_list[i + 1]

        up_point = point_details.get(up_id)
        down_point = point_details.get(down_id)

        if not up_point or not down_point:
            continue  # 跳过缺失点位
        preID = down_point["preBaseStationID"]
        if preID != up_id:
            continue    # 跳过非区间点位

        dist = down_point["distance"]
        direction = down_point["direction"]
        laneNumber = down_point["laneNumber"]
        roadLimitSpeed = down_point["roadLimitSpeed"]
        splitMergeFlag = down_point["splitMergeFlag"]
        down_gantry_id_list = [down_id]
        if splitMergeFlag == 1:
            rampBaseStationID = down_point["rampBaseStationID"]
            if not math.isnan(rampBaseStationID):
                down_gantry_id_list = [down_id, int(rampBaseStationID)]
        down_gantry_id_str = [str(gantry_id) for gantry_id in down_gantry_id_list]
        section_dict[str(section_id)] = {
            "up_gantry_id": [str(up_id)],
            "down_gantry_id": down_gantry_id_str,
            "direction": 0 if direction == "上行" else 1,
            "lane_num": int(laneNumber),
            "dist": round(dist, 3),
            "car_max_speed": int(roadLimitSpeed),
            "is_fork": splitMergeFlag
        }

        section_id += 1

    return section_dict


def read_xlsx(file_path):
    result_dict = {}
    df = pd.read_excel(file_path)
    # 自定义列名映射关系
    new_columns = {
        'IP': 'cameraIP',
        '基站ID': 'baseStationID',
        '前基站ID': 'preBaseStationID',
        '经度': 'longitude',
        '纬度': 'latitude',
        '桩号': 'PileNumber',
        '距离': 'distance',
        '方向': 'direction',
        '设备类型': 'deviceType',
        '车道数量': 'laneNumber',
        '道路限速': 'roadLimitSpeed',
        '分合流': 'splitMergeFlag',
        '匝道基站ID': 'rampBaseStationID'
    }
    # 修改列名，只保留 new_columns 中包含的列，并重命名
    df_filtered = df.filter(items=new_columns.keys()).rename(columns=new_columns)
    camera_type_grouped = df_filtered.groupby('deviceType')
    camera_type_dict = {name: group for name, group in camera_type_grouped}
    if '卡口摄像机' not in camera_type_dict:
        print("没有卡口摄像机")
    else:
        kako_camera_info_group = camera_type_dict['卡口摄像机']
        kako_up_down_grouped = kako_camera_info_group.groupby('direction')
        kako_up_down_dict = {name: group for name, group in kako_up_down_grouped}
        if '上行' not in kako_up_down_dict:
            print("门架没有上行")
        else:
            kako_up_camera_info_group = kako_up_down_dict['上行']
            # 将 baseStationID 列设为索引，并转为字典，格式为 {baseStationID: {其他列}}
            kako_up_camera_dict = kako_up_camera_info_group.set_index('baseStationID').to_dict(orient='index')
            print(kako_up_camera_dict)
            result_dict["kako_up_camera_dict"] = kako_up_camera_dict
            # 根据字典获取路由列表
            kako_up_camera_list = sort_by_pre_base_station(kako_up_camera_dict)
            result_dict["kako_up_camera_list"] = kako_up_camera_list
        if '下行' not in kako_up_down_dict:
            print("门架没有下行")
        else:
            kako_down_camera_info_group = kako_up_down_dict['下行']
            kako_down_camera_dict = kako_down_camera_info_group.set_index('baseStationID').to_dict(orient='index')
            print(kako_down_camera_dict)
            result_dict["kako_down_camera_dict"] = kako_down_camera_dict
            kako_down_camera_list = sort_by_pre_base_station(kako_down_camera_dict)
            result_dict["kako_down_camera_list"] = kako_down_camera_list
    if '枪机' not in camera_type_dict:
        print("没有枪机")
        return
    up_down_grouped = camera_type_dict['枪机'].groupby('direction')
    up_down_dict = {name: group for name, group in up_down_grouped}
    if '上行' not in up_down_dict:
        print("没有上行或下行")
    else:
        up_camera_info_group = up_down_dict['上行']
        up_camera_dict = up_camera_info_group.set_index('baseStationID').to_dict(orient='index')
        print(up_camera_dict)
        result_dict["up_camera_dict"] = up_camera_dict
        up_camera_list = sort_by_pre_base_station(up_camera_dict)
        result_dict["up_camera_list"] = up_camera_list
    if '下行' not in up_down_dict:
        print("没有下行")
    else:
        down_camera_info_group = up_down_dict['下行']
        down_camera_dict = down_camera_info_group.set_index('baseStationID').to_dict(orient='index')
        print(down_camera_dict)
        result_dict["down_camera_dict"] = down_camera_dict
        down_camera_list = sort_by_pre_base_station(down_camera_dict)
        result_dict["down_camera_list"] = down_camera_list

    return result_dict


def save_config_files(result_dict, device_info_file, config_file):
    device_info = {"route_info": {"kakou": {}}, "device_info": {"kakou": {}}}
    gantry_info = {}
    if "up_camera_list" in result_dict:
        device_info["route_info"]["up"] = result_dict["up_camera_list"]
        gantry_info["up"] = {}
    if "down_camera_list" in result_dict:
        device_info["route_info"]["down"] = result_dict["down_camera_list"]
        gantry_info["down"] = {}
    if "kako_up_camera_list" in result_dict:
        device_info["route_info"]["kakou"]["up"] = result_dict["up_camera_list"]
    if "kako_down_camera_list" in result_dict:
        device_info["route_info"]["kakou"]["down"] = result_dict["down_camera_list"]
    if "up_camera_dict" in result_dict:
        device_info["device_info"]["up"] = result_dict["up_camera_dict"]
    if "down_camera_dict" in result_dict:
        device_info["device_info"]["down"] = result_dict["down_camera_dict"]
    if "kako_up_camera_dict" in result_dict:
        device_info["device_info"]["kakou"]["up"] = result_dict["up_camera_dict"]
    if "kako_down_camera_dict" in result_dict:
        device_info["device_info"]["kakou"]["down"] = result_dict["down_camera_dict"]

    kakou_list = []
    kakou_dict = {}
    if "up" in device_info["device_info"]["kakou"]:
        kakou_dict.update(copy.deepcopy(device_info["device_info"]["kakou"]["up"]))
        kakou_list += device_info["route_info"]["kakou"]["up"]
        del device_info["device_info"]["kakou"]["up"]
    if "down" in device_info["device_info"]["kakou"]:
        kakou_dict.update(copy.deepcopy(device_info["device_info"]["kakou"]["down"]))
        kakou_list += device_info["route_info"]["kakou"]["down"]
        del device_info["device_info"]["kakou"]["down"]
    device_info["device_info"]["kakou"] = kakou_dict
    if kakou_dict:
        gantry_info["kakou"] = {}
    with open(device_info_file, "w", encoding="utf-8") as f:
        json.dump(device_info, f, ensure_ascii=False, indent=4)
        print(f"设备信息已保存至 {device_info_file}")

    config = {
        "ConfigData": {
            "kafka_host": "10.102.1.113:9092",
            "kafka_up_cars_topic": "e1_data_nq01",
            "kafka_down_cars_topic": "e1_data_na02",
            "kafka_kakou_cars_topic": "kako_data",
            "kafka_status_topic": "device_info",
            "kafka_status": "kafka_status_wanji",
            "kafka_device_status": "device_status",
            "kafka_event_topic": "b5_data",
            "clean_duration_time": 2,
            "all_time_move": 0.5,
            "all_time_interval": 5,
            "congestion_level_num": 4,
            "switch_timeout": 0.5,
            "min_switch_interval": 2,
            "SpeedLimit": {
                "120": {"l0": 90, "l1": 70, "l2": 50, "l3": 30},
                "110": {"l0": 85, "l1": 65, "l2": 45, "l3": 25},
                "100": {"l0": 80, "l1": 60, "l2": 40, "l3": 20},
                "90": {"l0": 70, "l1": 55, "l2": 35, "l3": 20},
                "80": {"l0": 60, "l1": 50, "l2": 35, "l3": 20},
                "70": {"l0": 55, "l1": 45, "l2": 30, "l3": 20},
                "60": {"l0": 50, "l1": 40, "l2": 30, "l3": 20}
            },
            "DensityLimit": {"l1": 20, "l2": 30, "l3": 40},
            "threshold": {
                "flow": 0.33,
                "speed": 0.4,
                "pass_rate": 70,
                "slow_num": 5
            },
            "gantry_info": {}
        }
    }
    if "up" in gantry_info:
        gantry_info["up"] = build_section_dict(device_info["route_info"]["up"], device_info["device_info"]["up"], 10001)
    if "down" in gantry_info:
        gantry_info["down"] = build_section_dict(device_info["route_info"]["down"], device_info["device_info"]["down"], 20001)
    if "kakou" in gantry_info:
        gantry_info["kakou"] = build_section_dict(kakou_list, device_info["device_info"]["kakou"], 30001)
    config["ConfigData"]["gantry_info"] = gantry_info
    with open(config_file, "w", encoding="utf-8") as f:
        json.dump(config, f, ensure_ascii=False, indent=4)
        print(f"设备信息已保存至 {config_file}")


if __name__ == '__main__':
    dir = os.path.dirname(os.path.abspath(__file__))
    config_path = os.path.join(dir, "Config")
    file_path = os.path.join(config_path, "device_info.xlsx")
    ouput_file1 = os.path.join(config_path, "device_info-0718.json")
    ouput_file2 = os.path.join(config_path, "config-0718.json")
    xlsx_dict = read_xlsx(file_path)
    save_config_files(xlsx_dict, ouput_file1, ouput_file2)

